package com.example.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.admin.common.util.JwtUtil;
import com.example.admin.entity.SysMenu;
import com.example.admin.entity.SysUser;
import com.example.admin.entity.SysRole;
import com.example.admin.entity.SysUserRole;
import com.example.admin.entity.SysRoleMenu;
import com.example.admin.mapper.SysMenuMapper;
import com.example.admin.mapper.SysUserMapper;
import com.example.admin.mapper.SysRoleMapper;
import com.example.admin.mapper.SysUserRoleMapper;
import com.example.admin.mapper.SysRoleMenuMapper;
import com.example.admin.model.dto.LoginDTO;
import com.example.admin.model.dto.RegisterDTO;
import com.example.admin.model.vo.LoginVO;
import com.example.admin.service.AuthService;
import com.example.admin.common.util.UserContext;
import com.example.admin.common.util.PasswordEncoder;
import com.example.admin.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import javax.servlet.http.HttpSession;

@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysMenuMapper menuMapper;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private SysRoleMenuMapper roleMenuMapper;

    @Autowired
    private HttpSession session;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(RegisterDTO registerDTO) {
        log.info("用户注册: {}", registerDTO.getUsername());
        try {
            // 验证两次密码是否相同
            if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
                throw new BusinessException("两次输入的密码不一致");
            }

            // 验证验证码
            String captcha = (String) session.getAttribute("captcha");
            if (captcha == null || !captcha.equals(registerDTO.getCaptcha().toLowerCase())) {
                throw new BusinessException("验证码错误");
            }
            session.removeAttribute("captcha");

            // 检查用户名是否已存在
            Integer count = userMapper.selectCount(
                    new LambdaQueryWrapper<SysUser>()
                            .eq(SysUser::getUsername, registerDTO.getUsername())
            );
            if (count > 0) {
                throw new BusinessException("用户名已存在");
            }

            // 创建用户
            SysUser user = new SysUser();
            user.setUsername(registerDTO.getUsername());
            user.setPassword(PasswordEncoder.encode(registerDTO.getPassword()));
            user.setNickname(registerDTO.getNickname());
            user.setStatus(1);
            userMapper.insert(user);
            log.info("用户创建成功: {}", user.getId());

            // 分配默认角色
            SysRole userRole = roleMapper.selectOne(
                    new LambdaQueryWrapper<SysRole>()
                            .eq(SysRole::getCode, "ROLE_USER")
            );
            if (userRole == null) {
                userRole = new SysRole();
                userRole.setName("普通用户");
                userRole.setCode("ROLE_USER");
                roleMapper.insert(userRole);
                log.info("创建普通用户角色: {}", userRole.getId());
            }

            // 建立用户和角色的关联
            SysUserRole userRoleRelation = new SysUserRole();
            userRoleRelation.setUserId(user.getId());
            userRoleRelation.setRoleId(userRole.getId());
            userRoleMapper.insert(userRoleRelation);
            log.info("用户角色关联创建成功: {} - {}", user.getId(), userRole.getId());

            // 为普通用户分配基础菜单权限
            List<SysMenu> basicMenus = menuMapper.selectList(null);

            if (!basicMenus.isEmpty()) {
                for (SysMenu menu : basicMenus) {
                    SysRoleMenu roleMenu = new SysRoleMenu();
                    roleMenu.setRoleId(userRole.getId());
                    roleMenu.setMenuId(menu.getId());
                    roleMenuMapper.insert(roleMenu);
                }
                log.info("分配基础菜单权限成功: {} 个", basicMenus.size());
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("用户注册失败", e);
            throw new BusinessException("注册失败，请稍后重试", e.getMessage());
        }
    }

    @Override
    public LoginVO login(LoginDTO loginDTO) {
        log.info("用户登录: {}", loginDTO.getUsername());
        try {
            // 验证验证码
            String captcha = (String) session.getAttribute("captcha");
            if (captcha == null || !captcha.equals(loginDTO.getCaptcha().toLowerCase())) {
                throw new BusinessException("验证码错误");
            }
            session.removeAttribute("captcha");

            // 查询用户
            SysUser user = userMapper.selectOne(
                    new LambdaQueryWrapper<SysUser>()
                            .eq(SysUser::getUsername, loginDTO.getUsername())
            );

            if (user == null) {
                throw new BusinessException("用户名或密码错误");
            }

            // 验证密码
            if (!PasswordEncoder.matches(loginDTO.getPassword(), user.getPassword())) {
                throw new BusinessException("用户名或密码错误");
            }

            // 生成token
            String token = jwtUtil.generateToken(user.getUsername());

            // 返回登录信息
            LoginVO loginVO = new LoginVO();
            loginVO.setToken(token);
            loginVO.setUsername(user.getUsername());
            loginVO.setNickname(user.getNickname());

            log.info("用户登录成功: {}", user.getId());
            return loginVO;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("用户登录失败", e);
            throw new BusinessException("登录失败，请稍后重试", e.getMessage());
        }
    }

    @Override
    public List<SysMenu> getCurrentUserMenus() {
        return menuMapper.selectByUserId(UserContext.getUser().getId());
    }
} 